///<refernce path="/api/vendor/jquery.js" />
///<refernce path="/api/vendor/knockout.js" />

(function (ko) {

    ko.observable.fn.revertable = function () {

        var self = this, originalValue = self();

        if (!originalValue) {
            self.subscribe(function () {
                originalValue = originalValue || self();
            });
        }

        self.commit = function () {
            originalValue = self();
        };

        self.revert = function () {
            self(originalValue || '');
        };

        self.isDirty = function () {
            return (self() != originalValue);
        };

        return self;
    };

    //wrapper for an observable that protects value until committed - http://jsfiddle.net/rniemeyer/jKXRb/
    ko.revertableObservable = function (initialValue) {
        //private variables
        var cache = ko.observable(initialValue), actual = ko.observable(initialValue);

        //cache the current value, so we can potentially revert back to it
        actual.commit = function () { cache(actual()); };

        //revert back to the cached value
        actual.revert = function () { actual(cache()); };

        actual.isDirty = function() { return actual() != cache(); };

        return actual;
    };
    
    ko.bindingHandlers.editableText = {
        init: function (element, valueAccessor) {
            $(element).on('blur', function () {
                $(this).parent().css("background-color", "white");
                var observable = valueAccessor();
                observable($(this).text());
            });

            $(element).focus(function () {
                $(this).parent().css("background-color", "lightgray");
            });
        },
        update: function (element, valueAccessor) {
            var value = ko.utils.unwrapObservable(valueAccessor());
            $(element).text(value);
        }
    };

    ko.observableArray.fn.distinct = function (prop) {
        var self = this;
        self.index = {};
        self.index[prop] = ko.observable({});

        ko.computed(function () {
            //rebuild index
            var propIndex = {};

            ko.utils.arrayForEach(self(), function (item) {
                var key = ko.utils.unwrapObservable(item[prop]);
                if (key) {
                    propIndex[key] = propIndex[key] || [];
                    propIndex[key].push(item);
                }
            });

            self.index[prop](propIndex);
        });

        return self;
    };

    // useful for turning off binding of nested bindings
    ko.bindingHandlers.stopBinding = {
        init: function () {
            return { controlsDescendantBindings: true };
        }
    };

    // Here's a custom Knockout binding that makes elements shown/hidden via jQuery's fadeIn()/fadeOut() methods
    // Could be stored in a separate utility library
    ko.bindingHandlers.fadeVisible = {
        init: function (element, valueAccessor) {
            // Initially set the element to be instantly visible/hidden depending on the value
            var value = valueAccessor();
            $(element).toggle(ko.utils.unwrapObservable(value)); // Use "unwrapObservable" so we can handle values that may or may not be observable
        },
        update: function (element, valueAccessor) {
            // Whenever the value subsequently changes, slowly fade the element in or out
            var value = valueAccessor();

            ko.utils.unwrapObservable(value) ? $(element).fadeIn() : $(element).fadeOut();
        }
    };

    ko.bindingHandlers.executeOnEnter = {
        init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
            var allBindings = allBindingsAccessor();
            $(element).keypress(function (event) {
                var keyCode = (event.which ? event.which : event.keyCode);
                if (keyCode === 13 || keyCode === 9) {
                    allBindings.executeOnEnter.call(viewModel);
                    return false;
                }
                return true;
            });
        }
    };

    //ko.bindingHandlers.monthpicker = {
    //    init: function (element, valueAccessor, allBindingsAccessor) {
    //        //initialize datepicker with some optional options
    //        var options = allBindingsAccessor().datepickerOptions || { autoclose: true, format: 'mm/yyyy', startView: 'month', minViewMode: 'months' };
    //        var observable = valueAccessor();
    //        $(element).datepicker(options).on("changeDate", function (ev) {
    //            observable(moment(ev.date).format("MM/YYYY"));
    //        });

    //        $(element).change(function () {
    //            observable($(this).attr('value'));
    //        });
    //    },
    //    update: function (element, valueAccessor) {
    //        var value = ko.utils.unwrapObservable(valueAccessor());
    //        if (!value) return;
    //        $(element).datepicker("setDate", moment(value, "MM/YYYY").toDate());
    //    }
    //};

    ////http://jdewit.github.com/bootstrap-timepicker/
    //ko.bindingHandlers.timepicker = {
    //    init: function (element, valueAccessor, allBindingsAccessor) {
    //        //initialize timepicker with some optional options
    //        var options = allBindingsAccessor().timepickerOptions || {};
    //        $(element).timepicker(options).on("changeTime.timepicker", function (ev) {
    //            var observable = valueAccessor();
    //            observable(ev.time.value);
    //        });

    //        //handle disposal (if KO removes by the template binding)
    //        ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
    //            $(element).timepicker("remove");
    //        });

    //    },
    //    update: function (element, valueAccessor) {
    //        var value = ko.utils.unwrapObservable(valueAccessor()), current = $(element).timepicker("getTime");

    //        if (value - current !== 0) {
    //            $(element).timepicker("setTime", value || '');
    //        }
    //    }
    //};
    
   

})(ko);